<template>
  <el-row :gutter="20" class="h-full">
    <el-button
      class="fixed ml-2"
      :icon="User"
      circle
      v-if="!isShowTable"
      @click="dialog = true"
    />
    <el-col :span="spanValue"
      ><div class="bg-white rounded shadow-xl p-6 box-border h-full">
        <el-row align="middle"
          ><el-col :span="spanValue1">
            <div class="flex flex-col items-center overflow-hidden select-none">
              <div class="flex items-center">
                <el-icon
                  :size="80"
                  class="iconStyle"
                  @mousedown="
                    (e:any) => handleControlTurnFront(e, ...keyMap.LEFTFRONT)
                  "
                  @mouseup=" (e:any) => endControlTurnFront(e, ...keyMap.TURNBACK)"
                  @touchstart="
                     (e:any) => handleControlTurnFront(e, ...keyMap.LEFTFRONT)
                  "
                  @touchend=" (e:any) => endControlTurnFront(e, ...keyMap.TURNBACK)"
                >
                  <Icon icon="mdi:arrow-left-top-bold" />
                </el-icon>
                <el-icon
                  :size="90"
                  class="iconStyle"
                  @mousedown=" (e:any) => handleControl(e, ...keyMap.FRONT)"
                  @mouseup=" (e:any) => endControl(e, ...keyMap.FRONTBACK)"
                  @touchstart=" (e:any) => handleControl(e, ...keyMap.FRONT)"
                  @touchend=" (e:any) => endControl(e, ...keyMap.FRONTBACK)"
                >
                  <Icon icon="mdi:arrow-up-thick"
                /></el-icon>
                <el-icon
                  :size="80"
                  class="iconStyle"
                  @mousedown="
                     (e:any) => handleControlTurnFront(e, ...keyMap.RIGHTFRONT)
                  "
                  @mouseup=" (e:any) => endControlTurnFront(e, ...keyMap.TURNBACK)"
                  @touchstart="
                     (e:any) => handleControlTurnFront(e, ...keyMap.RIGHTFRONT)
                  "
                  @touchend=" (e:any) => endControlTurnFront(e, ...keyMap.TURNBACK)"
                >
                  <Icon icon="mdi:arrow-right-top-bold" />
                </el-icon>
              </div>
              <div class="flex items-center">
                <el-icon
                  :size="90"
                  class="iconStyle"
                  @mousedown=" (e:any) => handleControl(e, ...keyMap.LEFT)"
                  @mouseup=" (e:any) => endControl(e, ...keyMap.TURNBACK)"
                  @touchstart=" (e:any) => handleControl(e, ...keyMap.LEFT)"
                  @touchend=" (e:any) => endControl(e, ...keyMap.TURNBACK)"
                >
                  <Icon icon="mdi:arrow-left-thick"
                /></el-icon>
                <el-icon
                  :size="90"
                  class="iconStyle"
                  @mousedown=" (e:any) => handleControl(e, ...keyMap.BACK)"
                  @mouseup=" (e:any) => endControl(e, ...keyMap.FRONTBACK)"
                  @touchstart=" (e:any) => handleControl(e, ...keyMap.BACK)"
                  @touchend=" (e:any) => endControl(e, ...keyMap.FRONTBACK)"
                >
                  <Icon icon="mdi:arrow-down-thick" />
                </el-icon>
                <el-icon
                  :size="90"
                  class="iconStyle"
                  @mousedown=" (e:any) => handleControl(e, ...keyMap.RIGHT)"
                  @mouseup=" (e:any) => endControl(e, ...keyMap.TURNBACK)"
                  @touchstart=" (e:any) => handleControl(e, ...keyMap.RIGHT)"
                  @touchend=" (e:any) => endControl(e, ...keyMap.TURNBACK)"
                >
                  <Icon icon="mdi:arrow-right-thick" />
                </el-icon>
              </div></div
          ></el-col>

          <el-col :span="spanValue1">
            <div class="btnStyle">
              当前机器人：{{ robotName
              }}<el-button
                class=""
                :icon="Setting"
                circle
                @click="openSettingDialog()"
              />
            </div>
            <div class="btnStyle">
              <div>手柄：</div>
              <div>
                {{ isConnect
                }}<el-icon
                  :size="12"
                  :class="
                    isConnect === '已连接' ? ' text-green-700 ' : 'text-red-500'
                  "
                  ><Icon
                    :icon="
                      isConnect === '已连接'
                        ? 'fa6-regular:circle-check'
                        : 'fa6-regular:circle-xmark'
                    "
                /></el-icon>
              </div>
            </div>
            <div class="btnStyle">
              <div class="flex items-center">舵机1：</div>
              <el-switch
                class="select-none"
                v-model="tailRodValueOne"
                active-text="展开"
                inactive-text="伸缩"
                :disabled="!robotCode || isConnect === '已连接'"
                @change="
                  () =>
                    handleDirection(
                      'X',
                      tailRodValueOne,
                      tailRodValue,
                      ledValue
                    )
                "
              />
            </div>
            <div class="btnStyle">
              <div class="flex items-center">舵机2：</div>
              <el-switch
                v-model="tailRodValue"
                active-text="展开"
                inactive-text="伸缩"
                :disabled="!robotCode || isConnect === '已连接'"
                @change="
                  () =>
                    handleDirection(
                      'Y',
                      tailRodValue,
                      tailRodValueOne,
                      ledValue
                    )
                "
              />
            </div>
            <div class="btnStyle">
              <div class="flex items-center">LED开关：</div>
              <el-switch
                v-model="ledValue"
                active-text="开灯"
                inactive-text="关灯"
                :disabled="!robotCode || isConnect === '已连接'"
                @change="
                  () =>
                    handleDirection(
                      'V',
                      ledValue,
                      tailRodValue,
                      tailRodValueOne
                    )
                "
              />
            </div>
            <div class="btnStyle">
              <div class="flex items-center">电量：</div>
              <div class="w-full py-2">
                <el-progress
                  :percentage="battery"
                  :stroke-width="10"
                  :height="10"
                />
              </div>
            </div>
            <div class="btnStyle">小球经度：{{ lat }}</div>
            <div class="btnStyle">小球纬度：{{ lon }}</div>
            <div class="p-2">
              <el-button
                type="success"
                v-if="isSplit"
                circle
                @click="changeComponent()"
                >切换</el-button
              >
              <el-button type="danger" circle @click="changeSplit()"
                >分屏</el-button
              >
            </div>
          </el-col>
        </el-row>
      </div></el-col
    >
    <el-col :span="spanValue" v-if="isShowTable"
      ><div id="table" class="bg-white rounded shadow-xl p-6 box-border h-full">
        <el-table
          :height="tableHeight"
          v-loading="loading"
          :data="robotData"
          :stripe="true"
          :border="true"
          class="tableStyle"
          highlight-current-row
          @current-change="handleCurrentChange"
        >
          <el-table-column
            prop="code"
            label="code"
            header-align="center"
            align="center"
          />
          <el-table-column
            prop="name"
            label="name"
            header-align="center"
            align="center"
          />
          <el-table-column
            prop="type"
            label="type"
            header-align="center"
            align="center"
          />
          <el-table-column
            prop="status"
            label="status"
            header-align="center"
            align="center"
          />
        </el-table></div
    ></el-col>
    <el-drawer v-model="dialog" title="请选择机器人" direction="rtl" size="50%">
      <el-table
        :height="tableHeight"
        v-loading="loading"
        :data="robotData"
        :stripe="true"
        :border="true"
        class="tableStyle"
        highlight-current-row
        @current-change="handleCurrentChange"
      >
        <el-table-column
          prop="code"
          label="code"
          header-align="center"
          align="center"
        />
        <el-table-column
          prop="name"
          label="name"
          header-align="center"
          align="center"
        />
        <el-table-column
          prop="type"
          label="type"
          header-align="center"
          align="center"
        />
        <el-table-column
          prop="status"
          label="status"
          header-align="center"
          align="center"
        />
      </el-table>
    </el-drawer>
    <SettingDialog
      v-model:visible="dialogVisible"
      :size="sizeStyle"
      :axesObject="axesObject"
      :btnsObject="btnsObject"
      :mergedKeys="mergedKeys"
      @changeSettingData="handleSettingData"
    ></SettingDialog>
  </el-row>
</template>
<script lang="ts" setup>
import SettingDialog from "../components/SettingDialog.vue";
import { Icon } from "@iconify/vue";
import { User, Setting } from "@element-plus/icons-vue";
import type { ComputedRef } from "vue";
import {
  computed,
  onBeforeUnmount,
  onMounted,
  reactive,
  ref,
  watch,
} from "vue";
import { ElMessage } from "element-plus";
import { fetchList, getRobotData } from "../../api/robot";
import { updateRobotControl } from "../../api/robotRemoteControl";
import useGamepad from "../composables/useGamepad";
import useGamepadBtn from "../composables/useGamepadBtn";

const dialog = ref(false);
const isShowTable = ref(true);
const tableHeight = ref(100);
const spanValue = ref(12);
const spanValue1 = ref(12);
const sizeStyle = ref();
const tailRodValueOne = ref(false);
const tailRodValue = ref(false);
const ledValue = ref(false);
const loading = ref(false);
const robotData = ref([]);
const robotCode = ref(0);
const robotType = ref("");
const robotName = ref("无");
const battery = ref(0);
const lat = ref("0");
const lon = ref("0");
const dialogVisible = ref(false);

/**声明参数常量 */
const keyMap: {
  FRONT: [string, number];
  LEFT: [string, number];
  BACK: [string, number];
  RIGHT: [string, number];
  LEFTFRONT: [string, number, number];
  RIGHTFRONT: [string, number, number];
  FRONTBACK: [string, number];
  TURNBACK: [string, number];
} = {
  FRONT: ["L", 2],
  LEFT: ["R", 2],
  BACK: ["L", -2],
  RIGHT: ["R", -2],
  LEFTFRONT: ["R", 2, 2],
  RIGHTFRONT: ["R", -2, 2],
  FRONTBACK: ["L", 0],
  TURNBACK: ["R", 0],
};

/** 声明控制变量 */
interface myFormData {
  [key: string]: any;
}

const settingData: myFormData = reactive({
  forward: "",
  left: "",
  right: "",
  backward: "",
  startlight: "",
  backlight: "",
  firstrod: "",
  secondrod: "",
});
function handleSettingData(v: any) {
  Object.assign(settingData, v);
}

const {
  initGamepad,
  disconnectGamepad,
  isConnect,
  direction,
  directionType,
  isDirection,
  clickedButton,
  newAxes,
  newBtns,
} = useGamepad({ settingData });

/** 监听手柄数据变化 */
const axesObject: any = ref({});
const btnsObject: any = ref({});

watch(
  newAxes,
  (newValues) => {
    newValues.forEach((value, index) => {
      axesObject.value[index] = value;
    });
  },
  { immediate: true }
);

watch(
  newBtns,
  (newValues) => {
    newValues.forEach((value, index) => {
      btnsObject.value[index] = value.value;
    });
  },
  { immediate: true }
);

onMounted(() => {
  // 添加窗口大小改变事件监听器
  window.addEventListener("resize", updateSpan);
  // 初始化时立即调用一次
  updateSpan();
  tableHeight.value =
    (document.getElementById("table")?.clientHeight || 160) - 60;
  getRobotList();
});

/** 视频/地图组件切换判断 */
const isGroup = ref(false);
const isSplit = ref(true);

const updateSpan = () => {
  // 如果窗口宽度小于1000px，spanValue为24，否则为12
  spanValue.value = window.innerWidth < 1000 ? 24 : 12;
  spanValue1.value = window.innerWidth < 1000 ? 24 : 12;
  isShowTable.value = window.innerWidth < 1000 ? false : true;
  sizeStyle.value =
    window.innerWidth < 500
      ? 95 + "%"
      : window.innerWidth < 820
      ? 80 + "%"
      : window.innerWidth < 1100
      ? 60 + "%"
      : 50 + "%";
};

watch(robotCode, () => {
  disconnectGamepad();
  initGamepad();
});

watch([directionType, direction, isDirection], () => {
  if (isConnect.value === "已连接") {
    handleGamepadControl(
      directionType.value,
      direction.value,
      isDirection.value
    );
  }
});

watch(clickedButton, (i: number) => {
  if (i === null) return;
  const actionGetter = (actionMap.value as any)[i];
  actionGetter && actionGetter();
  clickedButton.value = null;
});

const mergedKeys: any = ref([]);

function openSettingDialog() {
  dialogVisible.value = true;
  const axesKeys = Object.keys(axesObject.value);
  const btnsKeys = Object.keys(btnsObject.value);
  mergedKeys.value = [...new Set([...axesKeys, ...btnsKeys])];
}

const emit = defineEmits(["hanlePoint", "hanleComponent", "hanleSplit"]);

function changeComponent() {
  isGroup.value = !isGroup.value;
  emit("hanleComponent", isGroup.value);
}

function changeSplit() {
  isSplit.value = !isSplit.value;
  emit("hanleSplit", isSplit.value);
}
let timer: any;
let timer1: any;
let timer2: any;

/**
 * 获取机器人数据
 */
async function getRobotList() {
  loading.value = true;
  try {
    const { data } = await fetchList({ limit: 9999, RType: "sphere" });
    robotData.value = data.list;
    loading.value = false;
  } catch {
    loading.value = false;
  }
}

/**
 * 选择机器人
 * @param row
 */

let isFirstUpdate: any;

async function handleCurrentChange(row: any) {
  isFirstUpdate = true;
  updatedRobotData(row);
}

async function updatedRobotData(row: any) {
  clearTimeout(timer1);
  const [robotData] = await Promise.all([getRobotData({ code: row.code })]);
  const { list } = robotData.data;
  battery.value = list[0].battery;
  lat.value = list[0].lat;
  lon.value = list[0].lon;
  robotName.value = row.name;
  robotCode.value = row.code;
  robotType.value = row.type;
  if (isFirstUpdate) {
    tailRodValueOne.value = list[0].x ? true : false;
    tailRodValue.value = list[0].y ? true : false;
    ledValue.value = list[0].v ? false : true;
    isFirstUpdate = false;
  }
  emit("hanlePoint", { lat: lat.value, lon: lon.value });
  timer1 = setTimeout(async () => {
    updatedRobotData(row);
  }, 1000);
}

let isLed: any;
/**
 * 操控机器人-尾杆/led切换开关功能
 * @param type
 * @param val
 */

async function handleDirection(type: any, val1: any, val2: any, val3: any) {
  if (isConnect.value === "未连接") {
    clearTimeout(timer2);
    let data = {
      robot: robotCode.value,
      type: "navigation",
      [type]: type === "V" ? (val1 ? "0" : "1") : val1 ? "1" : "0",
      [type === "X" ? "Y" : type === "Y" ? "X" : "Y"]: val2 ? "1" : "0",
      [type === "X" ? "V" : type === "V" ? "X" : "V"]:
        type === "V" ? (val3 ? "1" : "0") : val3 ? "0" : "1",
    };
    await updateRobotControl(data);
    isLed = ledValue.value;
    timer2 = setTimeout(async () => {
      if (isLed === true) {
        handleDirection(type, val1, val2, val3);
      }
    }, 400);
  }
}

const {
  handleGamepadControl,
  toggleLedCloseAway,
  toggleLedStartAway,
  toggleGear1Away,
  toggleGear2Away,
} = useGamepadBtn({
  robotCode,
  ledValue,
  tailRodValueOne,
  tailRodValue,
  direction,
});
/**
 * 操控机器人-前进、后退、左右转、停止
 * @param type
 * @param val
 */
async function handleControl(e: any, type: any, val: any) {
  if (isConnect.value === "未连接") {
    clearTimeout(timer);
    clearTimeout(timer1);
    isLed = false;
    buttons.value = e.target;
    buttons.value.style.color = "red";
    if (!robotCode.value) {
      return ElMessage({ type: "warning", message: "请选择机器人" });
    }
    handleRobotControl(type, val);
    timer = setTimeout(async () => {
      handleControl(e, type, val);
    }, 400);
  }
}

function endControl(e: any, type: any, val: any) {
  if (isConnect.value === "未连接") {
    clearTimeout(timer); // 清除定时器
    buttons.value = e.target;
    buttons.value.style.color = "rgb(59, 141, 235)";
    handleRobotControl(type, val);
    isLed = ledValue.value;
    timer = setTimeout(async () => {
      if (isLed) {
        handleDirection(
          "V",
          ledValue.value,
          tailRodValue.value,
          tailRodValueOne.value
        );
      }
    }, 400);
  }
}

async function handleRobotControl(type: any, val: any) {
  let data = {
    type: "navigation",
    robot: robotCode.value,
    X: tailRodValueOne.value ? "1" : "0",
    Y: tailRodValue.value ? "1" : "0",
    V: ledValue.value ? "0" : "1",
    [type]: val,
  };
  await updateRobotControl(data);
}

const buttons = ref();
async function handleControlTurnFront(e: any, type: any, val: any, l: any) {
  if (isConnect.value === "未连接") {
    clearTimeout(timer);
    clearTimeout(timer1);
    buttons.value = e.target;
    buttons.value.style.color = "red";
    isLed = false;
    if (!robotCode.value) {
      return ElMessage({ type: "warning", message: "请选择机器人" });
    }
    handleRobotTurnFront(type, val, l);
    timer = setTimeout(async () => {
      handleControlTurnFront(e, type, val, l);
    }, 400);
  }
}
function endControlTurnFront(e: any, type: any, val: any) {
  if (isConnect.value === "未连接") {
    clearTimeout(timer);
    buttons.value = e.target;
    buttons.value.style.color = "rgb(59, 141, 235)";
    handleRobotTurnFront(type, val, 0);
    isLed = ledValue.value;
    timer = setTimeout(async () => {
      if (isLed) {
        handleDirection(
          "V",
          ledValue.value,
          tailRodValue.value,
          tailRodValueOne.value
        );
      }
    }, 400);
  }
}

async function handleRobotTurnFront(type: any, val: any, l: any) {
  let data = {
    type: "navigation",
    robot: robotCode.value,
    X: tailRodValueOne.value ? "1" : "0",
    Y: tailRodValue.value ? "1" : "0",
    V: ledValue.value ? "0" : "1",
    [type]: val,
    L: l,
  };
  await updateRobotControl(data);
}

/** 手柄按钮控制 */
const actionMap: ComputedRef<object> = computed(() => {
  return {
    [settingData.firstrod]: toggleGear1Away,
    [settingData.secondrod]: toggleGear2Away,
    [settingData.backlight]: toggleLedCloseAway,
    [settingData.startlight]: toggleLedStartAway,
  };
});

onBeforeUnmount(() => {
  clearTimeout(timer);
  clearTimeout(timer1);
  clearTimeout(timer2);
  // 组件销毁时移除事件监听器
  window.removeEventListener("resize", updateSpan);
});
</script>

<style scoped lang="scss">
.iconStyle {
  color: rgb(59, 141, 235);
  border-radius: 0.375rem;
  cursor: pointer;
}
.icon {
  transform: rotate(45deg);
}
.btnTitleStyle {
  display: flex;
  justify-items: center;
}
.el-col {
  white-space: nowrap;
}
.btnStyle {
  display: flex;
  justify-content: space-between;
  margin: 4px 0;
  align-items: center;
}

@media screen and (max-width: 1050px) {
  .iconStyle {
    width: 65px;
    height: 65px;
    margin: 10px;
  }
  .btnStyle {
    font-size: 14px;
    overflow: hidden;
    justify-items: center;
    margin: 6px 0;
  }
}
@media screen and (max-width: 820px) {
  .btnStyle {
    font-size: 18px;
  }
}

@media screen and (max-width: 500px) {
  .btnStyle {
    font-size: 14px;
  }
  .tableStyle {
    font-size: 12px;
  }
}
</style>
